<?php
namespace Extend;

/**
 * sign加密类
 * Class KeyWorker
 * @package Extend
 */
class KeyWorker
{
    const ASN = 1;
    const PEM = 2;
    private $key;
    private $isPrivate;
    private $keyFormat;
    private $keyProvider;

    public function __construct($key, $keyFormat = KeyWorker::PEM)
    {

        $this->key = $key;
        $this->keyFormat = $keyFormat;
    }


    public function getKey()
    {
        $this->_makesure_provider();
        return $this->key;
    }

    public function encrypt($data)
    {
        $this->_makesure_provider();

        if ($this->isPrivate) {
            $r = openssl_private_encrypt($data, $encrypted, $this->keyProvider, OPENSSL_PKCS1_PADDING);
        } else {
            $r = openssl_public_encrypt($data, $encrypted, $this->keyProvider, OPENSSL_PKCS1_PADDING);
        }

        return $r ? $data = base64_encode($encrypted) : null;
    }

    public function decrypt($data)
    {
        $this->_makesure_provider();
        $data = base64_decode($data);
        if ($this->isPrivate) {
            $r = openssl_private_decrypt($data, $decrypted, $this->keyProvider, OPENSSL_PKCS1_PADDING);
        } else {
            $r = openssl_public_decrypt($data, $decrypted, $this->keyProvider, OPENSSL_PKCS1_PADDING);
        }

        return $r ? $decrypted : null;
    }

    public function _makesure_provider()
    {
        if ($this->keyProvider == null) {
            $this->isPrivate = strlen($this->key) > 500;

            switch ($this->keyFormat) {
                case self::ASN: {

                    $this->key = chunk_split($this->key, 64, "\r\n");//转换为pem格式的公钥
                    if ($this->isPrivate) {
                        $this->key = "-----BEGIN PRIVATE KEY-----\r\n" . $this->key . "-----END PRIVATE KEY-----";
                    } else {
                        $this->key = "-----BEGIN PUBLIC KEY-----\r\n" . $this->key . "-----END PUBLIC KEY-----";
                    }

                    break;
                }
            }

            $this->keyProvider = $this->isPrivate ? openssl_pkey_get_private($this->key) : openssl_pkey_get_public($this->key);
        }
    }

    /**
     * 生成签名
     *
     * @param string 签名材料
     * @param string 签名编码（base64/hex/bin）
     * @return 签名值
     */
    public function sign($data, $privateKey)
    {
        $ret = false;
        if (openssl_sign($data, $ret, $privateKey)) {
            $ret = $this->_encode($ret, 'base64');
        }
        return $ret;
    }

    /**
     * 验证签名
     *
     * @param string 签名材料
     * @param string 签名值
     * @param string 签名编码（base64/hex/bin）
     * @return bool
     */
    public function verify($data, $sign, $publicKey)
    {
        if (empty($data) || empty($sign)) {
            return '验签必要参数为空';
        }
        //去除转字符串中的反斜杠
        //$data =  stripslashes($data);
        //base64解码
        $deSign = base64_decode($sign);
        $result = openssl_verify($data, $deSign, $publicKey, OPENSSL_ALGO_SHA1) === 1;
        return $result;
    }

    private function _encode($data, $code)
    {
        switch (strtolower($code)) {
            case 'base64':
                $data = base64_encode('' . $data);
                break;
            case 'hex':
                $data = bin2hex($data);
                break;
            case 'bin':
            default:
        }
        return $data;
    }

    private function _decode($data, $code)
    {
        switch (strtolower($code)) {
            case 'base64':
                $data = base64_decode($data);
                break;
            case 'hex':
                $data = $this->_hex2bin($data);
                break;
            case 'bin':
            default:
        }
        return $data;
    }

    private function _hex2bin($hex = false)
    {
        $ret = $hex !== false && preg_match('/^[0-9a-fA-F]+$/i', $hex) ? pack("H*", $hex) : false;
        return $ret;
    }
}
///////////////这是最后一条////////////////////////////////////////